package com.rede.didiok.admin.service.impl;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rede.didiok.admin.dao.SystemConfigDao;
import com.rede.didiok.admin.entity.SystemConfigEntity;
import com.rede.didiok.admin.service.SystemConfigService;
import com.rede.didiok.common.constant.conf.MessageConf;
import com.rede.didiok.common.constant.conf.RedisConf;
import com.rede.didiok.common.constant.conf.SQLConf;
import com.rede.didiok.common.constant.conf.SysConf;
import com.rede.didiok.common.constant.global.Constants;
import com.rede.didiok.common.constant.global.ErrorCode;
import com.rede.didiok.common.dto.admin.SystemConfigDto;
import com.rede.didiok.common.enums.FilePriorityEnum;
import com.rede.didiok.common.enums.OpenStatusEnum;
import com.rede.didiok.common.enums.StatusEnum;
import com.rede.didiok.common.exception.exceptionType.QueryException;
import com.rede.didiok.common.utils.JsonUtils;
import com.rede.didiok.common.utils.RedisUtil;
import com.rede.didiok.common.utils.ResultUtil;
import com.rede.didiok.common.utils.StringUtils;


@Service("systemConfigService")
public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigDao, SystemConfigEntity> implements SystemConfigService {

    @Autowired
    private RedisUtil redisUtil;

    /***************************** admin:start **************************/
    // region  didiok-admin

    /**
     * 获取系统配置
     *
     * @return
     */
    @Override
    public SystemConfigEntity getOneSystemConfig() {
        // 从Redis中获取系统配置
        // TODO 注意一下：redis中如果存储的是 SystemConfigEntity，从redis中再获取是否可以用SystemConfigDto接收
        String systemConfigJson = redisUtil.get(RedisConf.SYSTEM_CONFIG);
        if (StringUtils.isEmpty(systemConfigJson)) {
            QueryWrapper<SystemConfigEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.orderByDesc(SQLConf.CREATE_TIME);
            queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
            queryWrapper.last(SysConf.LIMIT_ONE);
            SystemConfigEntity systemConfig = this.getOne(queryWrapper);
            if (systemConfig == null) {
                throw new QueryException(MessageConf.SYSTEM_CONFIG_IS_NOT_EXIST);
            } else {
                // 将系统配置存入Redis中【设置过期时间24小时】
                SystemConfigDto systemConfigDto = new SystemConfigDto();
                BeanUtils.copyProperties(systemConfig, systemConfigDto);
                redisUtil.setEx(RedisConf.SYSTEM_CONFIG, JsonUtils.objectToJson(systemConfigDto), 24, TimeUnit.HOURS);
                // 上面存储的是 SystemConfigEntity 类型的，下面在存储一个 SystemConfigDto 类型的
//                redisUtil.setEx(RedisConf.SYSTEM_CONFIG, JsonUtils.objectToJson(systemConfig), 24, TimeUnit.HOURS);
            }
            return systemConfig;
        } else {
            SystemConfigDto systemConfigDto = JsonUtils.jsonToPojo(systemConfigJson, SystemConfigDto.class);
            if (systemConfigDto == null) {
                throw new QueryException(ErrorCode.QUERY_DEFAULT_ERROR, "系统配置转换错误，请检查系统配置，或者清空Redis后重试！");
            }
            SystemConfigEntity systemConfig = new SystemConfigEntity();
            BeanUtils.copyProperties(systemConfigDto, systemConfig);

            return systemConfig;
        }
    }

    /**
     * 通过Key前缀清空Redis缓存
     *
     * @param key
     * @return
     */
    @Override
    public String cleanRedisByKey(List<String> key) {
        if (key == null) {
            return ResultUtil.errorWithMessage(MessageConf.OPERATION_FAIL);
        }
        key.forEach(item -> {
            // 表示清空所有key
            if (RedisConf.ALL.equals(item)) {
                Set<String> keys = redisUtil.keys(Constants.SYMBOL_STAR);
                redisUtil.delete(keys);
            } else {
                // 获取Redis中特定前缀
                Set<String> keys = redisUtil.keys(item + Constants.SYMBOL_STAR);
                redisUtil.delete(keys);
            }
        });
        return ResultUtil.successWithMessage(MessageConf.OPERATION_SUCCESS);

    }

    /**
     * 修改系统配置
     *
     * @param systemConfigDto
     * @return
     */
    @Override
    public String editSystemConfig(SystemConfigDto systemConfigDto) {
        // 图片必须选择上传到一个区域
        if (OpenStatusEnum.CLOSE.equals(systemConfigDto.getUploadLocal()) && OpenStatusEnum.CLOSE.equals(systemConfigDto.getUploadQiNiu()) && OpenStatusEnum.CLOSE.equals(systemConfigDto.getUploadMinio()) && OpenStatusEnum.CLOSE.equals(systemConfigDto.getUploadAlioss())) {
            return ResultUtil.errorWithMessage(MessageConf.PICTURE_MUST_BE_SELECT_AREA);
        }
        // 图片显示优先级为本地优先，必须开启图片上传本地
        if ((FilePriorityEnum.LOCAL.equals(systemConfigDto.getPicturePriority())
                || FilePriorityEnum.LOCAL.equals(systemConfigDto.getContentPicturePriority()))
                && OpenStatusEnum.CLOSE.equals(systemConfigDto.getUploadLocal())) {
            return ResultUtil.errorWithMessage(MessageConf.MUST_BE_OPEN_LOCAL_UPLOAD);
        }
        // 图片显示优先级为七牛云优先，必须开启图片上传七牛云
        if ((FilePriorityEnum.QI_NIU.equals(systemConfigDto.getPicturePriority())
                || FilePriorityEnum.QI_NIU.equals(systemConfigDto.getContentPicturePriority()))
                && OpenStatusEnum.CLOSE.equals(systemConfigDto.getUploadQiNiu())) {
            return ResultUtil.errorWithMessage(MessageConf.MUST_BE_OPEN_QI_NIU_UPLOAD);
        }
        // 图片显示优先级为Minio优先，必须开启图片上传Minio
        if ((FilePriorityEnum.MINIO.equals(systemConfigDto.getPicturePriority())
                || FilePriorityEnum.MINIO.equals(systemConfigDto.getContentPicturePriority()))
                && OpenStatusEnum.CLOSE.equals(systemConfigDto.getUploadMinio())) {
            return ResultUtil.errorWithMessage(MessageConf.MUST_BE_OPEN_MINIO_UPLOAD);
        }
        //图片显示优先级为阿里OSS优先，必须开启图片上传阿里OSS
        if ((FilePriorityEnum.ALIOSS.equals(systemConfigDto.getPicturePriority())
                || FilePriorityEnum.ALIOSS.equals(systemConfigDto.getContentPicturePriority()))
                && OpenStatusEnum.CLOSE.equals(systemConfigDto.getUploadAlioss())) {
            return ResultUtil.errorWithMessage(MessageConf.MUST_BE_OPEN_ALIOSS_UPLOAD);
        }

        // 开启Email邮件通知时，必须保证Email字段不为空
        if (OpenStatusEnum.OPEN.equals(systemConfigDto.getStartEmailNotification()) && StringUtils.isEmpty(systemConfigDto.getEmail())) {
            return ResultUtil.errorWithMessage(MessageConf.MUST_BE_SET_EMAIL);
        }
        if (StringUtils.isEmpty(systemConfigDto.getUid())) {
            SystemConfigEntity systemConfig = new SystemConfigEntity();
            // 设置七牛云、邮箱、系统配置相关属性【使用Spring工具类提供的深拷贝】
            BeanUtils.copyProperties(systemConfigDto, systemConfig, SysConf.STATUS);
            systemConfig.insert();
        } else {
            SystemConfigEntity systemConfig = this.getById(systemConfigDto.getUid());

//            // 断是否更新了图片显示优先级【如果更新了，需要请求Redis中的博客，否者将导致图片无法正常显示】
//            if (!systemConfigDto.getPicturePriority().equals(systemConfig.getPicturePriority())) {
//                blogService.deleteRedisByBlog();
//            }
            // TODO 判断是否更新了图片显示优先级【如果更新了，需要请求Redis中的榜单成员详情，否者将导致图片无法正常显示】


            // 设置七牛云、邮箱、系统配置相关属性【使用Spring工具类提供的深拷贝】
            BeanUtils.copyProperties(systemConfigDto, systemConfig, SysConf.STATUS, SysConf.UID);
            systemConfig.updateById();

        }
        // 更新系统配置成功后，需要删除Redis中的系统配置
        redisUtil.delete(RedisConf.SYSTEM_CONFIG);
        // 修改配置时候，清空Redis的图片信息
        Set<String> fileUrls = redisUtil.keys(RedisConf.FILE_UID_TO_URL + Constants.SYMBOL_COLON + Constants.SYMBOL_STAR);
        redisUtil.delete(fileUrls);
        return ResultUtil.successWithMessage(MessageConf.UPDATE_SUCCESS);
    }

    // endregion
    /***************************** admin:end **************************/



    /***************************** web:start **************************/
    // region didiok-web

    /**
     * 获取系统配置中的搜索模式
     *
     * @return
     */
    @Override
    public String getSearchModel() {
        SystemConfigEntity systemConfig = this.getOneSystemConfig();
        return String.valueOf(systemConfig.getSearchModel());
    }

    // endregion
    /***************************** web:end **************************/

    /**
     * 获取一条系统配置信息
     */
    @Override
    public SystemConfigEntity getSystemConfig() {
        QueryWrapper<SystemConfigEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc(SQLConf.CREATE_TIME);
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.last(SysConf.LIMIT_ONE);
        return this.getOne(queryWrapper);
    }
}